package in.muton.edushare.components.calendar.api;

import in.muton.edushare.EduShareSession;
import in.muton.edushare.auth.roles.CourseRoleCheck;
import in.muton.edushare.auth.roles.DeptRoleCheck;
import in.muton.edushare.auth.roles.UnivRoleCheck;
import in.muton.edushare.schedules.widgets.DateHelper;
import in.muton.edushare.wicket.models.CayenneList;

import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.edushare.common.dao.CourseInstancesDAO;
import com.edushare.common.dao.DepartmentsDAO;
import com.edushare.common.dao.ScheduleDAO;
import com.edushare.common.dao.UniversitiesDAO;
import com.edushare.common.dao.UsersDAO;
import com.edushare.common.orm.ORMInterface;
import com.edushare.common.vo.CourseInstances;
import com.edushare.common.vo.Departments;
import com.edushare.common.vo.Groups;
import com.edushare.common.vo.Messages;
import com.edushare.common.vo.ScheduleNotifications;
import com.edushare.common.vo.Schedules;
import com.edushare.common.vo.Universities;
import com.edushare.common.vo.Users;

public class CalendarInterface {
	
	private static Log log = LogFactory.getLog(CalendarInterface.class);
	
	public static CayenneList<Schedules> getSchedules(Groups group) {
		ScheduleDAO sDAO = new ScheduleDAO(EduShareSession.get()
				.getSessionORMInterface());
		List<Schedules> schList = sDAO.getSchedulesByCreatorId(
												group.getGroupId(), 
												Messages.RECEIVER_TYPE_GROUP
												);
		return new CayenneList<Schedules>(schList);
	}
	
	public static CayenneList<Schedules> getSchedules(Departments dept) {
		ScheduleDAO sDAO = new ScheduleDAO(EduShareSession.get()
				.getSessionORMInterface());
		List<Schedules> schList = sDAO.getSchedulesByCreatorId(dept
				.getDepartmentId(), Messages.RECEIVER_TYPE_DEPARTMENT);
		return new CayenneList<Schedules>(schList);
	}

	public static CayenneList<Schedules> getSchedules(Universities univ) {
		ScheduleDAO sDAO = new ScheduleDAO(EduShareSession.get()
				.getSessionORMInterface());
		List<Schedules> schList = sDAO.getSchedulesByCreatorId(univ
				.getUniversityId(), Messages.RECEIVER_TYPE_UNIVERSITY);
		return new CayenneList<Schedules>(schList);
	}

	public static CayenneList<Schedules> getSchedules(CourseInstances course) {
		ScheduleDAO sDAO = new ScheduleDAO(EduShareSession.get()
				.getSessionORMInterface());
		List<Schedules> schList = sDAO.getSchedulesByCreatorId(course
				.getCourseInstanceId(), Messages.RECEIVER_TYPE_COURSE);
		return new CayenneList<Schedules>(schList);
	}

	public static CayenneList<Schedules> getSchedules(Users user) {
		List<ScheduleNotifications> snL = user.getSchedules();
		CayenneList<Schedules> schList = new CayenneList<Schedules>(null);
		for (ScheduleNotifications s : snL) {
			if (s.getActionStatus() != ScheduleNotifications.CANCELLED) {
				schList.add(s.getSchedule());
			}
		}
		return schList;
	}

	public static Schedules getEventById(int id) {
		return new ScheduleDAO(EduShareSession.get().getSessionORMInterface())
				.getScheduleById(id);
	}

	public static boolean isCalendarEntryOfDate(Date date, Schedules event) {
		Date start = event.getSchStart();
		Date end = event.getRepetitionEnd();

		switch (event.getFrequency()) {
		case Schedules.EVENT_ONCE_ONLY:
			if (DateHelper.sameDay(start, date))
				return true;
			return false;

		case Schedules.EVENT_DAILY:
			if (DateHelper.sameDay(start, date)
					|| (DateHelper.after(date, start) && DateHelper.before(
							date, end)) || DateHelper.sameDay(end, date))
				return true;
			return false;
		case Schedules.EVENT_WEEKLY:
			if (DateHelper.sameDay(start, date))
				return true;
			else if (DateHelper.after(date, start)
					&& DateHelper.before(date, end)
					&& DateHelper.getDayOfWeek(date) == DateHelper
							.getDayOfWeek(start))
				return true;
			else if (DateHelper.getDayOfWeek(date) == DateHelper
					.getDayOfWeek(start)
					&& DateHelper.sameDay(end, date))
				return true;
			return false;

		case Schedules.EVENT_MONTHLY:
			if (DateHelper.sameDay(start, date))
				return true;
			else if (DateHelper.after(date, start)
					&& DateHelper.before(date, end)
					&& DateHelper.getDayOfMonth(date) == DateHelper
							.getDayOfMonth(start))
				return true;
			return false;
		default:
			return false;
		}
	}

	public boolean isAunthenticated(Schedules sch, Users u) {
		ORMInterface orm = EduShareSession.get().getSessionORMInterface();
		if (sch.getCreatorType() == Messages.RECEIVER_TYPE_UNIVERSITY) {
			Universities univ = new UniversitiesDAO(orm).getUnivById(sch
					.getSchCreator());
			UnivRoleCheck urc = new UnivRoleCheck(univ, u);
			if (urc.isAdmin()) {
				return true;
			}
		}
		if (sch.getCreatorType() == Messages.RECEIVER_TYPE_DEPARTMENT) {
			Departments dept = new DepartmentsDAO(orm).getDepartmentByPk(sch
					.getSchCreator());
			DeptRoleCheck drc = new DeptRoleCheck(dept, u);
			if (drc.isPrimaryAdmin() || drc.isUnivAdmin())
				return true;
		}
		if (sch.getCreatorType() == Messages.RECEIVER_TYPE_COURSE) {
			CourseInstances ci = new CourseInstancesDAO(orm)
					.getCourseInstanceById(sch.getSchCreator());
			CourseRoleCheck crc = new CourseRoleCheck(ci, u);
			if (crc.isTeacher() || crc.isAdmin())
				return true;
		}

		if (sch.getCreatorType() == Messages.RECEIVER_TYPE_USER) {
			Users user = new UsersDAO(orm).getUserByPk(sch.getSchCreator());
			if (user == u)
				return true;
		}
		return false;
	}
	
	public static boolean isFutureEvent(Schedules sch, Date d){
		Date start = sch.getSchStart();
		Date end = sch.getRepetitionEnd();
		switch (sch.getFrequency()) {
		case Schedules.EVENT_ONCE_ONLY:
			if (DateHelper.timeBefore(d, start))
				return true;
			return false;

		case Schedules.EVENT_DAILY:
			if (DateHelper.timeBefore(d, end))
				return true;
			return false;
		case Schedules.EVENT_WEEKLY:
			if (DateHelper.timeBefore(d, end))
				return true;
			return false;

		case Schedules.EVENT_MONTHLY:
			if (DateHelper.timeBefore(d, end))
				return true;
		default:
			return false;
		}
	}

	public static Date getNextOccurence(Schedules sch, Date d){
		Date start = sch.getSchStart();
		Date end = sch.getRepetitionEnd();
		
		log.debug("Start date = "+start +"; End date = "+end);
		
		if(sch.getFrequency() != Schedules.EVENT_ONCE_ONLY)
			if(DateHelper.after(d, end)){
				log.debug("Past event.");
				return new Date(0);
			}
		
		switch (sch.getFrequency()) {
		case Schedules.EVENT_ONCE_ONLY:
			log.debug("Single event");
			return sch.getSchStart();
		case Schedules.EVENT_MONTHLY:
			DateHelper dh = new DateHelper(start);
			while(true){
				Date addedDate = dh.getDate();
				if(DateHelper.timeBefore(d, addedDate)){
					log.debug("Monthly event date = "+addedDate);
					return addedDate;
				}
				dh.addMonths(1);
			}
		case Schedules.EVENT_WEEKLY:
			DateHelper dh1 = new DateHelper(start);
			while(true){
				Date addedDate = dh1.getDate();
				if(DateHelper.timeBefore(d, addedDate)){
					log.debug("Weekly event date = "+addedDate);
					return addedDate;
				}
				dh1.addWeeks(1);
			}
		case Schedules.EVENT_DAILY:
			DateHelper dh2 = new DateHelper(start);
			while(true){
				Date addedDate = dh2.getDate();
				if(DateHelper.timeBefore(d, addedDate)){
					log.debug("Daily event date = "+addedDate);
					return addedDate;
				}
				dh2.addDays(1);
			}
		}
		return new Date(0);
	}
}
